#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QTcpSocket>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 修改一下窗口标题
    this->setWindowTitle("服务器");
    // 创建tcpserver实例
    tcpserver = new QTcpServer(this);
    // 通过信号槽来指定如何处理链接
    connect(tcpserver, &QTcpServer::newConnection, this, &Widget::processConnection);
    // 绑定端口并监听
    bool ret = tcpserver->listen(QHostAddress::Any, 8888);
    if (!ret) {
        QMessageBox::critical(this, "服务器启动失败", tcpserver->errorString());
        exit(-1);
    }
}

Widget::~Widget()
{
    delete ui;
}

void Widget::processConnection()
{
    // 通过tcpserver拿到socket对象，然后通过这个socket对象来和客户端进行通信
    QTcpSocket* clientsocket = tcpserver->nextPendingConnection();
    QString log = "客户端 [" + clientsocket->peerAddress().toString() + " : " + QString::number(clientsocket->peerPort()) + "]上线啦!!";
    ui->listWidget->addItem(log);
    // 通过信号槽，来处理客户端发来的请求的情况
    connect(clientsocket, &QTcpSocket::readyRead, this, [=](){
        // 读取出数据
        QString request = clientsocket->readAll();
        // 根据请求，来处理响应
        QString response = process(request);
        // 将响应写回客户端
        clientsocket->write(response.toUtf8());
        // 把上述信息也记录到日志中
        QString log = "[" + clientsocket->peerAddress().toString() + " : " + QString::number(clientsocket->peerPort()) + "] + " +"request: " + request + ", response: " + response;
        ui->listWidget->addItem(log);
    });

    // 处理客户端断开连接的情况
    // 也是通过信号槽来进行处理
    connect(clientsocket, &QTcpSocket::disconnected, this, [=](){
       // 把断开连接的信息通过日志显示出来
        QString log = "客户端 [" + clientsocket->peerAddress().toString() + " : " + QString::number(clientsocket->peerPort()) + "]断开连接了!!";
        ui->listWidget->addItem(log);
        // 手动释放clientsocket
        // 这里的delete一定要保证是最后执行的，不能被跳过，所以直接使用delete是下策，使用deleteLater更合适
        clientsocket->deleteLater(); // 这个deleteLater并不是立即销毁，而是告诉Qt在下一轮时间循环中在进行销毁
        // (槽函数都是在事件循环中执行的，进入下一轮时间循环，也就意味着你上一轮事件循环结束了，槽函数也就肯定执行完毕了)
    });

}

QString Widget::process(QString &request)
{
    return request;
}

